home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume13 / gmcalc / part02 < prev    next >
Encoding:
Text File  |  1990-06-05  |  57.0 KB  |  1,944 lines

  1. Newsgroups: comp.sources.misc
  2. From: daveg@csvax.caltech.edu (David Gillespie)
  3. Subject: v13i028: Emacs Calculator 1.01, part 02/19
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 13, Issue 28
  7. Submitted-by: daveg@csvax.caltech.edu (David Gillespie)
  8. Archive-name: gmcalc/part02
  9.  
  10. ---- Cut Here and unpack ----
  11. #!/bin/sh
  12. # this is part 2 of a multipart archive
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file calc.el continued
  15. #
  16. CurArch=2
  17. if test ! -r s2_seq_.tmp
  18. then echo "Please unpack part 1 first!"
  19.      exit 1; fi
  20. ( read Scheck
  21.   if test "$Scheck" != $CurArch
  22.   then echo "Please unpack part $Scheck next!"
  23.        exit 1;
  24.   else exit 0; fi
  25. ) < s2_seq_.tmp || exit 1
  26. echo "x - Continuing file calc.el"
  27. sed 's/^X//' << 'SHAR_EOF' >> calc.el
  28. X)
  29. X
  30. X(defun calc-record (val &optional prefix)
  31. X  (or calc-executing-macro
  32. X      (let* ((mainbuf (current-buffer))
  33. X         (buf (get-buffer-create "*Calc Trail*"))
  34. X         (calc-display-raw (eq calc-display-raw t))
  35. X         (fval (if val
  36. X               (if (stringp val)
  37. X               val
  38. X             (math-showing-full-precision
  39. X              (math-format-flat-expr val 0)))
  40. X             "")))
  41. X    (save-excursion
  42. X      (set-buffer buf)
  43. X      (if (not (eq major-mode 'calc-trail-mode))
  44. X          (calc-trail-mode mainbuf))
  45. X      (let ((aligned (calc-check-trail-aligned))
  46. X        (buffer-read-only nil))
  47. X        (goto-char (point-max))
  48. X        (cond ((null prefix) (insert "     "))
  49. X          ((> (length prefix) 5) (insert (substring prefix 0 5) " "))
  50. X          (t (insert (format "%4s " prefix))))
  51. X        (insert fval "\n")
  52. X        (let ((win (get-buffer-window buf)))
  53. X          (if (and aligned win (not (memq 'hold-trail calc-command-flags)))
  54. X          (progn
  55. X            (calc-trail-here))))
  56. X        (goto-char (1- (point-max)))))))
  57. X  val
  58. X)
  59. X
  60. X(defun calc-record-list (vals &optional prefix)
  61. X  (while vals
  62. X    (or (eq (car vals) 'top-of-stack)
  63. X    (progn
  64. X      (calc-record (car vals) prefix)
  65. X      (setq prefix "...")))
  66. X    (setq vals (cdr vals)))
  67. X)
  68. X
  69. X(defun calc-trail-display (flag &optional no-refresh)
  70. X  "Turn the Trail display on or off.
  71. XWith prefix argument 1, turn it on; with argument 0, turn it off."
  72. X  (interactive "P")
  73. X  (let* ((trail (get-buffer-create "*Calc Trail*"))
  74. X     (win (get-buffer-window trail)))
  75. X    (if (setq calc-display-trail
  76. X          (not (if flag (memq flag '(nil 0)) win)))
  77. X    (if (null win)
  78. X        (progn
  79. X          (if (and (boundp 'calc-trail-window-hook) calc-trail-window-hook)
  80. X          (run-hooks 'calc-trail-window-hook)
  81. X        (let ((w (split-window nil (/ (* (window-width) 2) 3) t)))
  82. X          (set-window-buffer w trail)))
  83. X          (calc-wrapper
  84. X           (or no-refresh
  85. X           (calc-refresh)))))
  86. X      (if win
  87. X      (progn
  88. X        (delete-window win)
  89. X        (calc-wrapper
  90. X         (or no-refresh
  91. X         (calc-refresh)))))
  92. X      (if (and (boundp 'overlay-arrow-position)
  93. X           (eq overlay-arrow-position calc-trail-pointer))
  94. X      (setq overlay-arrow-position nil)))
  95. X    trail)
  96. X)
  97. X
  98. X(defun calc-trail-here ()
  99. X  "Move the trail pointer to the current cursor line."
  100. X  (interactive)
  101. X  (if (eq major-mode 'calc-trail-mode)
  102. X      (progn
  103. X    (beginning-of-line)
  104. X    (if (bobp)
  105. X        (forward-line 1)
  106. X      (if (eobp)
  107. X          (forward-line -1)))
  108. X    (if (or (bobp) (eobp))
  109. X        (setq overlay-arrow-position nil)   ; trail is empty
  110. X      (set-marker calc-trail-pointer (point) (current-buffer))
  111. X      (setq overlay-arrow-string (concat (buffer-substring (point)
  112. X                                   (+ (point) 4))
  113. X                         ">")
  114. X        overlay-arrow-position calc-trail-pointer)
  115. X      (forward-char 4)
  116. X      (let ((win (get-buffer-window (current-buffer))))
  117. X        (if win
  118. X        (save-excursion
  119. X          (forward-line (/ (window-height) 2))
  120. X          (forward-line (- 1 (window-height)))
  121. X          (set-window-start win (point))
  122. X          (set-window-point win (+ calc-trail-pointer 4)))))))
  123. X    (error "Not in Calc Trail buffer"))
  124. X)
  125. X
  126. X
  127. X
  128. X
  129. X;;;; The Undo list.
  130. X
  131. X(defun calc-record-undo (rec)
  132. X  (or calc-executing-macro
  133. X      (if (memq 'undo calc-command-flags)
  134. X      (setq calc-undo-list (cons (cons rec (car calc-undo-list))
  135. X                     (cdr calc-undo-list)))
  136. X    (setq calc-undo-list (cons (list rec) calc-undo-list)
  137. X          calc-redo-list nil)
  138. X    (calc-set-command-flag 'undo)))
  139. X)
  140. X
  141. X
  142. X
  143. X;;; Arithmetic commands.
  144. X
  145. X(defun calc-binary-op (name func arg &optional ident unary)
  146. X  (if (null arg)
  147. X      (calc-enter-result 2 name (cons func (calc-top-list-n 2)))
  148. X    (calc-extensions)
  149. X    (calc-binary-op-fancy name func arg ident unary))
  150. X)
  151. X
  152. X(defun calc-unary-op (name func arg)
  153. X  (if (null arg)
  154. X      (calc-enter-result 1 name (list func (calc-top-n 1)))
  155. X    (calc-extensions)
  156. X    (calc-unary-op-fancy name func arg))
  157. X)
  158. X
  159. X
  160. X(defun calc-plus (arg)
  161. X  "Add the top two elements of the Calculator stack."
  162. X  (interactive "P")
  163. X  (calc-slow-wrapper
  164. X   (calc-binary-op "+" 'calcFunc-add arg 0))
  165. X)
  166. X
  167. X(defun calc-minus (arg)
  168. X  "Subtract the top two elements of the Calculator stack."
  169. X  (interactive "P")
  170. X  (calc-slow-wrapper
  171. X   (calc-binary-op "-" 'calcFunc-sub arg 0 'calcFunc-neg))
  172. X)
  173. X
  174. X(defun calc-times (arg)
  175. X  "Multiply the top two elements of the Calculator stack."
  176. X  (interactive "P")
  177. X  (calc-slow-wrapper
  178. X   (calc-binary-op "*" 'calcFunc-mul arg 1))
  179. X)
  180. X
  181. X(defun calc-divide (arg)
  182. X  "Divide the top two elements of the Calculator stack."
  183. X  (interactive "P")
  184. X  (calc-slow-wrapper
  185. X   (calc-binary-op "/" 'calcFunc-div arg 0 'calcFunc-inv))
  186. X)
  187. X
  188. X(defun calc-power (arg)
  189. X  "Compute y^x for the top two elements of the Calculator stack."
  190. X  (interactive "P")
  191. X  (calc-slow-wrapper
  192. X   (calc-binary-op "^" 'calcFunc-pow arg))
  193. X)
  194. X
  195. X(defun calc-mod (arg)
  196. X  "Compute the modulo of the top two elements of the Calculator stack."
  197. X  (interactive "P")
  198. X  (calc-slow-wrapper
  199. X   (calc-binary-op "%" 'calcFunc-mod arg))
  200. X)
  201. X
  202. X(defun calc-inv (arg)
  203. X  "Invert the number or square matrix on the top of the stack."
  204. X  (interactive "P")
  205. X  (calc-slow-wrapper
  206. X   (calc-unary-op "inv" 'calcFunc-inv arg))
  207. X)
  208. X
  209. X(defun calc-change-sign (arg)
  210. X  "Change the sign of the top element of the Calculator stack."
  211. X  (interactive "P")
  212. X  (calc-wrapper
  213. X   (calc-unary-op "chs" 'calcFunc-neg arg))
  214. X)
  215. X
  216. X
  217. X
  218. X;;; Stack management commands.
  219. X
  220. X(defun calc-enter (n)
  221. X  "Duplicate the top N elements of the Calculator stack.
  222. XWith a negative argument -N, duplicate the Nth element of the stack."
  223. X  (interactive "p")
  224. X  (calc-wrapper
  225. X   (cond ((< n 0)
  226. X      (calc-push (calc-top (- n))))
  227. X     ((= n 0)
  228. X      (calc-push-list (calc-top-list (calc-stack-size))))
  229. X     (t
  230. X      (calc-push-list (calc-top-list n)))))
  231. X)
  232. X
  233. X(defun calc-over (n)
  234. X  "Duplicate the Nth element of the Calculator stack.
  235. XWith a negative argument -N, duplicate the top N elements of the stack."
  236. X  (interactive "P")
  237. X  (if n
  238. X      (calc-enter (- (prefix-numeric-value n)))
  239. X    (calc-enter -2))
  240. X)
  241. X
  242. X(defun calc-pop (n)
  243. X  "Pop (and discard) the top N elements of the stack.
  244. XWith a negative argument -N, remove the Nth element from the stack."
  245. X  (interactive "P")
  246. X  (calc-wrapper
  247. X   (let* ((nn (prefix-numeric-value n))
  248. X      (top (and (null n) (calc-top 1))))
  249. X     (cond ((and (null n)
  250. X         (eq (car-safe top) 'incomplete)
  251. X         (> (length top) (if (eq (nth 1 top) 'intv) 3 2)))
  252. X        (calc-pop-push 1 (let ((tt (copy-sequence top)))
  253. X                   (setcdr (nthcdr (- (length tt) 2) tt) nil)
  254. X                   tt)))
  255. X       ((< nn 0)
  256. X        (calc-pop-stack 1 (- nn)))
  257. X       ((= nn 0)
  258. X        (calc-pop-stack (calc-stack-size)))
  259. X       (t
  260. X        (calc-pop-stack nn)))))
  261. X)
  262. X
  263. X(defun calc-roll-down (n)
  264. X  "Exchange the top two elements of the Calculator stack.
  265. XWith a numeric prefix, roll down the top N elements."
  266. X  (interactive "P")
  267. X  (calc-wrapper
  268. X   (let ((nn (prefix-numeric-value n)))
  269. X     (cond ((null n)
  270. X        (calc-roll-down-stack 2))
  271. X       ((> nn 0)
  272. X        (calc-roll-down-stack nn))
  273. X       ((= nn 0)
  274. X        (calc-pop-push-list (calc-stack-size)
  275. X                (reverse
  276. X                 (calc-top-list (calc-stack-size)))))
  277. X       (t
  278. X        (calc-roll-down-stack (calc-stack-size) (- nn))))))
  279. X)
  280. X
  281. X(defun calc-roll-up (n)
  282. X  "Roll up the top three elements of the Calculator stack.
  283. XWith a numeric prefix, roll up the top N elements."
  284. X  (interactive "P")
  285. X  (calc-wrapper
  286. X   (let ((nn (prefix-numeric-value n)))
  287. X     (cond ((null n)
  288. X        (calc-roll-up-stack 3))
  289. X       ((> nn 0)
  290. X        (calc-roll-up-stack nn))
  291. X       ((= nn 0)
  292. X        (calc-pop-push-list (calc-stack-size)
  293. X                (reverse
  294. X                 (calc-top-list (calc-stack-size)))))
  295. X       (t
  296. X        (calc-roll-up-stack (calc-stack-size) (- nn))))))
  297. X)
  298. X
  299. X
  300. X
  301. X
  302. X;;; Miscellaneous commands.
  303. X
  304. X(defun calc-precision (n)
  305. X  "Display current float precision for Calculator, or set precision to N digits."
  306. X  (interactive "NPrecision: ")
  307. X  (calc-wrapper
  308. X   (if (< (prefix-numeric-value n) 3)
  309. X       (error "Precision must be at least 3 digits.")
  310. X     (setq calc-internal-prec (prefix-numeric-value n))
  311. X     (calc-record calc-internal-prec "prec"))
  312. X   (message "Floating-point precision is %d digits." calc-internal-prec))
  313. X)
  314. X
  315. X
  316. X(defun calc-num-prefix-name (n)
  317. X  (cond ((eq n '-) "- ")
  318. X    ((equal n '(4)) "C-u ")
  319. X    ((consp n) (format "%d " (car n)))
  320. X    ((integerp n) (format "%d " n))
  321. X    (t ""))
  322. X)
  323. X
  324. X(defun calc-missing-key (n)
  325. X  "This is a placeholder for a command which needs to be loaded from calc-ext.
  326. XWhen this key is used, calc-ext (the Calculator extensions module) will be
  327. Xloaded and the keystroke automatically re-typed."
  328. X  (interactive "P")
  329. X  (calc-extensions)
  330. X  (if (keymapp (key-binding (char-to-string last-command-char)))
  331. X      (message "%s%c-" (calc-num-prefix-name n) last-command-char))
  332. X  (setq unread-command-char last-command-char
  333. X    prefix-arg n)
  334. X)
  335. X
  336. X(defun calc-why ()
  337. X  "Explain why the last result was unusual."
  338. X  (interactive)
  339. X  (if (not (eq this-command last-command))
  340. X      (setq calc-which-why calc-why))
  341. X  (if calc-which-why
  342. X      (progn
  343. X    (calc-explain-why (car calc-which-why))
  344. X    (setq calc-which-why (cdr calc-which-why)))
  345. X    (if calc-why
  346. X    (progn
  347. X      (message "(No further explanations available)")
  348. X      (setq calc-which-why calc-why))
  349. X      (message "No explanations available")))
  350. X)
  351. X(setq calc-which-why nil)
  352. X
  353. X(defun calc-flush-caches ()
  354. X  "Clear all caches used internally by the Calculator, such as the values of
  355. Xpi and e.  These values will be recomputed next time they are requested."
  356. X  (interactive)
  357. X  (calc-wrapper
  358. X   (setq math-lud-cache nil
  359. X     math-log2-cache nil
  360. X     math-max-digits-cache nil
  361. X     math-integral-cache nil
  362. X     math-units-table nil)
  363. X   (mapcar (function (lambda (x) (set x -100))) math-cache-list)
  364. X   (message "All internal calculator caches have been reset."))
  365. X)
  366. X(setq math-cache-list nil)
  367. X
  368. X
  369. X
  370. X;;;; Reading an expression in algebraic form.
  371. X
  372. X(defun calc-algebraic-entry ()
  373. X  "Read an algebraic expression (e.g., 1+2*3) and push the result on the stack."
  374. X  (interactive)
  375. X  (calc-wrapper
  376. X   (calc-alg-entry))
  377. X)
  378. X
  379. X(defun calc-auto-alg-entry ()
  380. X  "Begin entering an algebraic expression with a '$' or '\"' character."
  381. X  (interactive)
  382. X  (calc-wrapper
  383. X   (calc-alg-entry (char-to-string last-command-char)))
  384. X)
  385. X
  386. X(defun calc-alg-entry (&optional initial prompt)
  387. X  (let* ((calc-dollar-values (mapcar 'car-safe
  388. X                     (nthcdr calc-stack-top calc-stack)))
  389. X     (calc-dollar-used 0)
  390. X     (alg-exp (calc-do-alg-entry initial prompt t)))
  391. X    (let ((nvals (mapcar 'calc-normalize alg-exp)))
  392. X      (while alg-exp
  393. X    (calc-record (car alg-exp) "alg'")
  394. X    (calc-pop-push-record calc-dollar-used "" (car nvals))
  395. X    (setq alg-exp (cdr alg-exp)
  396. X          nvals (cdr nvals)
  397. X          calc-dollar-used 0)))
  398. X    (calc-handle-whys))
  399. X)
  400. X
  401. X(defun calc-do-alg-entry (&optional initial prompt no-normalize)
  402. X  (let* ((alg-exp 'error)
  403. X     (alg (read-from-minibuffer (or prompt "Algebraic: ")
  404. X                    (or initial "")
  405. X                    calc-alg-ent-map nil)))
  406. X    (if (eq alg-exp 'error)
  407. X    (if (eq (car (setq alg-exp (math-read-exprs alg)))
  408. X        'error)
  409. X        (error "Error: %s" (or (nth 2 exp) "Bad format"))))
  410. X    (or no-normalize
  411. X    (setq alg-exp (mapcar 'calc-normalize alg-exp)))
  412. X    alg-exp)
  413. X)
  414. X
  415. X(defvar calc-alg-ent-map nil "Keymap for use by the calc-algebraic-entry command.")
  416. X(if calc-alg-ent-map
  417. X    ()
  418. X  (setq calc-alg-ent-map (copy-keymap minibuffer-local-map))
  419. X  (define-key calc-alg-ent-map "'" 'calcAlg-previous)
  420. X  (define-key calc-alg-ent-map "\ep" 'calcAlg-plus-minus)
  421. X  (define-key calc-alg-ent-map "\em" 'calcAlg-mod)
  422. X  (define-key calc-alg-ent-map "\C-m" 'calcAlg-enter)
  423. X  (define-key calc-alg-ent-map "\C-j" 'calcAlg-enter)
  424. X)
  425. X
  426. X(defun calcAlg-plus-minus ()
  427. X  (interactive)
  428. X  (if (calc-minibuffer-contains ".* \\'")
  429. X      (insert "+/- ")
  430. X    (insert " +/- "))
  431. X)
  432. X
  433. X(defun calcAlg-mod ()
  434. X  (interactive)
  435. X  (if (not (calc-minibuffer-contains ".* \\'"))
  436. X      (insert " "))
  437. X  (if (calc-minibuffer-contains ".* mod +\\'")
  438. X      (if calc-previous-modulo
  439. X      (insert (math-format-flat-expr calc-previous-modulo 0))
  440. X    (beep))
  441. X    (insert "mod "))
  442. X)
  443. X
  444. X(defun calcAlg-previous ()
  445. X  (interactive)
  446. X  (if (calc-minibuffer-contains "\\`\\'")
  447. X      (if calc-previous-alg-entry
  448. X      (insert calc-previous-alg-entry)
  449. X    (beep))
  450. X    (insert "'"))
  451. X)
  452. X
  453. X(defun calcAlg-enter ()
  454. X  (interactive)
  455. X  (let ((exp (and (> (buffer-size) 0)
  456. X          (math-read-exprs (buffer-string)))))
  457. X    (if (eq (car-safe exp) 'error)
  458. X    (progn
  459. X      (goto-char (point-min))
  460. X      (forward-char (nth 1 exp))
  461. X      (beep)
  462. X      (calc-temp-minibuffer-message
  463. X       (concat " [" (or (nth 2 exp) "Error") "]"))
  464. X      (setq unread-command-char -1))
  465. X      (setq alg-exp (if (calc-minibuffer-contains "\\` *\\[ *\\'")
  466. X            '((incomplete vec))
  467. X              exp)
  468. X        calc-previous-alg-entry (buffer-string))
  469. X      (exit-minibuffer)))
  470. X)
  471. X
  472. X
  473. X
  474. X;;;; Reading a number using the minibuffer.
  475. X
  476. X(defun calcDigit-start ()
  477. X  "Begin digit entry in the Calculator."
  478. X  (interactive)
  479. X  (calc-wrapper
  480. X   (if calc-algebraic-mode
  481. X       (cond ((eq last-command-char ?e) (calc-alg-entry "1e"))
  482. X         ((eq last-command-char ?#) (calc-alg-entry
  483. X                     (format "%d#" calc-number-radix)))
  484. X         ((eq last-command-char ?_) (calc-alg-entry "-"))
  485. X         ((eq last-command-char ?@) (calc-alg-entry "0@ "))
  486. X         (t (calc-alg-entry (char-to-string last-command-char))))
  487. X     (let ((calc-digit-value 'yow)
  488. X       (calc-prev-char nil)
  489. X       (calc-prev-prev-char nil))
  490. X       (setq unread-command-char last-command-char)
  491. X       (let ((str (read-from-minibuffer "Calc: " ""
  492. X                    calc-digit-map)))
  493. X     (if (eq calc-digit-value 'yow)
  494. X         (setq calc-digit-value (math-read-number str))))
  495. X       (if (stringp calc-digit-value)
  496. X       (calc-alg-entry calc-digit-value)
  497. X     (if calc-digit-value
  498. X         (calc-push (calc-record (calc-normalize calc-digit-value)))))
  499. X       (if (eq calc-prev-char 'dots)
  500. X       (progn
  501. X         (calc-extensions)
  502. X         (calc-dots))))))
  503. X)
  504. X
  505. X(defun calcDigit-nondigit ()
  506. X  (interactive)
  507. X  (setq calc-digit-value (math-read-number (buffer-string)))
  508. X  (if (and (null calc-digit-value) (> (buffer-size) 0))
  509. X      (progn
  510. X    (beep)
  511. X    (calc-temp-minibuffer-message " [Bad format]"))
  512. X    (or (memq last-command-char '(32 10 13))
  513. X    (setq prefix-arg current-prefix-arg
  514. X          unread-command-char last-command-char))
  515. X    (exit-minibuffer))
  516. X)
  517. X
  518. X(defun calcDigit-algebraic ()
  519. X  (interactive)
  520. X  (if (calc-minibuffer-contains ".*[@oh] *[^'m ]+[^'m]*\\'")
  521. X      (calcDigit-key)
  522. X    (setq calc-digit-value (buffer-string))
  523. X    (exit-minibuffer))
  524. X)
  525. X
  526. X(defun calc-minibuffer-contains (rex)
  527. X  (save-excursion
  528. X    (goto-char (point-min))
  529. X    (looking-at rex))
  530. X)
  531. X
  532. X(defun calcDigit-key ()
  533. X  (interactive)
  534. X  (goto-char (point-max))
  535. X  (if (or (and (memq last-command-char '(?+ ?-))
  536. X           (> (buffer-size) 0)
  537. X           (/= (preceding-char) ?e))
  538. X      (and (memq last-command-char '(?m ?s))
  539. X           (not (calc-minibuffer-contains "[-+]?[0-9]+\\.?0*[@oh].*"))
  540. X           (not (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*"))))
  541. X      (calcDigit-nondigit)
  542. X    (if (calc-minibuffer-contains "\\([-+]?\\|.* \\)\\'")
  543. X    (cond ((memq last-command-char '(?. ?@)) (insert "0"))
  544. X          ((and (memq last-command-char '(?o ?h ?m))
  545. X            (not (calc-minibuffer-contains ".*#.*"))) (insert "0"))
  546. X          ((memq last-command-char '(?: ?e)) (insert "1"))
  547. X          ((eq last-command-char ?#)
  548. X           (insert (int-to-string calc-number-radix)))))
  549. X    (if (and (calc-minibuffer-contains "\\([-+]?[0-9]+#\\|[^:]*:\\)\\'")
  550. X         (eq last-command-char ?:))
  551. X    (insert "1"))
  552. X    (if (or (and (memq last-command-char '(?e ?h ?o ?m ?s ?p))
  553. X         (calc-minibuffer-contains ".*#.*"))
  554. X        (and (eq last-command-char ?n)
  555. X         (calc-minibuffer-contains "[-+]?\\(2[4-9]\\|[3-9][0-9]\\)#.*")))
  556. X    (setq last-command-char (upcase last-command-char)))
  557. X    (cond
  558. X     ((memq last-command-char '(?_ ?n))
  559. X      (goto-char (point-min))
  560. X      (if (and (search-forward " +/- " nil t)
  561. X           (not (search-forward "e" nil t)))
  562. X      (beep)
  563. X    (and (not (calc-minibuffer-contains ".*#.*"))
  564. X         (search-forward "e" nil t))
  565. X    (if (looking-at "+")
  566. X        (delete-char 1))
  567. X    (if (looking-at "-")
  568. X        (delete-char 1)
  569. X      (insert "-")))
  570. X      (goto-char (point-max)))
  571. X     ((eq last-command-char ?p)
  572. X      (if (or (calc-minibuffer-contains ".*\\+/-.*")
  573. X          (calc-minibuffer-contains ".*mod.*")
  574. X          (calc-minibuffer-contains ".*#.*")
  575. X          (calc-minibuffer-contains ".*[-+e:]\\'"))
  576. X      (beep)
  577. X    (if (not (calc-minibuffer-contains ".* \\'"))
  578. X        (insert " "))
  579. X    (insert "+/- ")))
  580. X     ((and (eq last-command-char ?M)
  581. X       (not (calc-minibuffer-contains
  582. X         "[-+]?\\(2[3-9]\\|[3-9][0-9]\\)#.*")))
  583. X      (if (or (calc-minibuffer-contains ".*\\+/-.*")
  584. X          (calc-minibuffer-contains ".*mod *[^ ]+")
  585. X          (calc-minibuffer-contains ".*[-+e:]\\'"))
  586. X      (beep)
  587. X    (if (calc-minibuffer-contains ".*mod \\'")
  588. X        (if calc-previous-modulo
  589. X        (insert (math-format-flat-expr calc-previous-modulo 0))
  590. X          (beep))
  591. X      (if (not (calc-minibuffer-contains ".* \\'"))
  592. X          (insert " "))
  593. X      (insert "mod "))))
  594. X     (t
  595. X      (insert (char-to-string last-command-char))
  596. X      (if (or (and (calc-minibuffer-contains "[-+]?\\(.*\\+/- *\\|.*mod *\\)?\\([0-9][0-9]?\\)#[0-9a-zA-Z]*\\(:[0-9a-zA-Z]*\\)?\\(:[0-9a-zA-Z]*\\)?\\'")
  597. X           (let ((radix (string-to-int
  598. X                 (buffer-substring
  599. X                  (match-beginning 2) (match-end 2)))))
  600. X             (and (>= radix 2)
  601. X              (<= radix 36)
  602. X              (or (memq last-command-char '(?# ?:))
  603. X                  (let ((dig (math-read-radix-digit
  604. X                      (upcase last-command-char))))
  605. X                (and dig
  606. X                     (< dig radix)))))))
  607. X          (save-excursion
  608. X        (goto-char (point-min))
  609. X             (looking-at
  610. X         "[-+]?\\(.*\\+/- *\\|.*mod *\\)?\\([0-9]+\\.?0*[@oh] *\\)?\\([0-9]+\\.?0*['m] *\\)?[0-9]*\\(\\.?[0-9]*\\(e[-+]?[0-9]*\\)?\\|[0-9]:\\([0-9]+:\\)?[0-9]*\\)?[\"s]?\\'")))
  611. X      (if (and (memq last-command-char '(?@ ?o ?h ?\' ?m))
  612. X           (string-match " " calc-hms-format))
  613. X          (insert " "))
  614. X    (if (and (eq this-command last-command)
  615. X         (eq last-command-char ?.))
  616. X        (if (eq calc-prev-char ?.)
  617. X        (progn
  618. X          (delete-backward-char 1)
  619. X          (if (calc-minibuffer-contains ".*\\.\\'")
  620. X              (delete-backward-char 1))
  621. X          (setq calc-prev-char 'dots
  622. X            last-command-char 32)
  623. X          (if calc-prev-prev-char
  624. X              (calcDigit-nondigit)
  625. X            (setq calc-digit-value nil)
  626. X            (exit-minibuffer)))
  627. X          ;; just ignore extra decimal point, anticipating ".."
  628. X          (delete-backward-char 1))
  629. X      (delete-backward-char 1)
  630. X      (beep)
  631. X      (calc-temp-minibuffer-message " [Bad format]"))))))
  632. X  (setq calc-prev-prev-char calc-prev-char
  633. X    calc-prev-char last-command-char)
  634. X)
  635. X
  636. X(defun calcDigit-letter ()
  637. X  (interactive)
  638. X  (if (calc-minibuffer-contains "[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#.*")
  639. X      (progn
  640. X    (setq last-command-char (upcase last-command-char))
  641. X    (calcDigit-key))
  642. X    (calcDigit-nondigit))
  643. X)
  644. X
  645. X(defun calcDigit-backspace ()
  646. X  (interactive)
  647. X  (goto-char (point-max))
  648. X  (cond ((calc-minibuffer-contains ".* \\+/- \\'")
  649. X     (backward-delete-char 5))
  650. X    ((calc-minibuffer-contains ".* mod \\'")
  651. X     (backward-delete-char 5))
  652. X    ((calc-minibuffer-contains ".* \\'")
  653. X     (backward-delete-char 2))
  654. X    (t (backward-delete-char 1)))
  655. X  (if (= (buffer-size) 0)
  656. X      (progn
  657. X    (setq last-command-char 10)
  658. X    (calcDigit-nondigit)))
  659. X)
  660. X
  661. X(defun calc-temp-minibuffer-message (m)
  662. X  "A Lisp version of temp_minibuffer_message from minibuf.c."
  663. X  (let ((savemax (point-max)))
  664. X    (save-excursion
  665. X      (goto-char (point-max))
  666. X      (insert m))
  667. X    (let ((inhibit-quit t))
  668. X      (sit-for 2)
  669. X      (delete-region savemax (point-max))
  670. X      (if quit-flag
  671. X      (setq quit-flag nil
  672. X        unread-command-char 7))))
  673. X)
  674. X
  675. X
  676. X
  677. X
  678. X
  679. X
  680. X
  681. X;;;; Arithmetic routines.
  682. X;;;
  683. X;;; An object as manipulated by one of these routines may take any of the
  684. X;;; following forms:
  685. X;;;
  686. X;;; integer                 An integer.  For normalized numbers, this format
  687. X;;;                is used only for -999999 ... 999999.
  688. X;;;
  689. X;;; (bigpos N0 N1 N2 ...)   A big positive integer, N0 + N1*1000 + N2*10^6 ...
  690. X;;; (bigneg N0 N1 N2 ...)   A big negative integer, - N0 - N1*1000 ...
  691. X;;;                Each digit N is in the range 0 ... 999.
  692. X;;;                Normalized, always at least three N present,
  693. X;;;                and the most significant N is nonzero.
  694. X;;;
  695. X;;; (frac NUM DEN)          A fraction.  NUM and DEN are small or big integers.
  696. X;;;                         Normalized, DEN > 1.
  697. X;;;
  698. X;;; (float NUM EXP)         A floating-point number, NUM * 10^EXP;
  699. X;;;                         NUM is a small or big integer, EXP is a small int.
  700. X;;;                Normalized, NUM is not a multiple of 10, and
  701. X;;;                abs(NUM) < 10^calc-internal-prec.
  702. X;;;                Normalized zero is stored as (float 0 0).
  703. X;;;
  704. X;;; (cplx REAL IMAG)        A complex number; REAL and IMAG are any of above.
  705. X;;;                Normalized, IMAG is nonzero.
  706. X;;;
  707. X;;; (polar R THETA)         Polar complex number.  Normalized, R > 0 and THETA
  708. X;;;                         is neither zero nor 180 degrees (pi radians).
  709. X;;;
  710. X;;; (vec A B C ...)         Vector of objects A, B, C, ...  A matrix is a
  711. X;;;                         vector of vectors.
  712. X;;;
  713. X;;; (hms H M S)             Angle in hours-minutes-seconds form.  All three
  714. X;;;                         components have the same sign; H and M must be
  715. X;;;                         numerically integers; M and S are expected to
  716. X;;;                         lie in the range [0,60).
  717. X;;;
  718. X;;; (sdev X SIGMA)          Error form, X +/- SIGMA.  When normalized,
  719. X;;;                         SIGMA > 0.  X and SIGMA are any real numbers,
  720. X;;;                         or symbolic expressions which are assumed real.
  721. X;;;
  722. X;;; (intv MASK LO HI)       Interval form.  MASK is 0=(), 1=(], 2=[), or 3=[].
  723. X;;;                         LO and HI are any real numbers, or symbolic
  724. X;;;                expressions which are assumed real, and LO < HI.
  725. X;;;                For [LO..HI], if LO = HI normalization produces LO,
  726. X;;;                and if LO > HI normalization produces [LO..LO).
  727. X;;;                For other intervals, if LO > HI normalization
  728. X;;;                sets HI equal to LO.
  729. X;;;
  730. X;;; (mod N M)                Number modulo M.  When normalized, 0 <= N < M.
  731. X;;;                N and M are real numbers.
  732. X;;;
  733. X;;; (var V S)            Symbolic variable.  V is a Lisp symbol which
  734. X;;;                represents the variable's visible name.  S is
  735. X;;;                the symbol which actually stores the variable's
  736. X;;;                value:  (var pi var-pi).
  737. X;;;
  738. X;;; In general, combining rational numbers in a calculation always produces
  739. X;;; a rational result, but if either argument is a float, result is a float.
  740. X
  741. X;;; In the following comments, [x y z] means result is x, args must be y, z,
  742. X;;; respectively, where the code letters are:
  743. X;;;
  744. X;;;    O  Normalized object (vector or number)
  745. X;;;    V  Normalized vector
  746. X;;;    N  Normalized number of any type
  747. X;;;    N  Normalized complex number
  748. X;;;    R  Normalized real number (float or rational)
  749. X;;;    F  Normalized floating-point number
  750. X;;;    T  Normalized rational number
  751. X;;;    I  Normalized integer
  752. X;;;    B  Normalized big integer
  753. X;;;    S  Normalized small integer
  754. X;;;    D  Digit (small integer, 0..999)
  755. X;;;    L  Normalized bignum digit list (without "bigpos" or "bigneg" symbol)
  756. X;;;       or normalized vector element list (without "vec")
  757. X;;;    P  Predicate (truth value)
  758. X;;;    X  Any Lisp object
  759. X;;;    Z  "nil"
  760. X;;;
  761. X;;; Lower-case letters signify possibly un-normalized values.
  762. X;;; "L.D" means a cons of an L and a D.
  763. X;;; [N N; n n] means result will be normalized if argument is.
  764. X;;; Also, [Public] marks routines intended to be called from outside.
  765. X;;; [This notation has been neglected in many recent routines.]
  766. X
  767. X;;; Reduce an object to canonical (normalized) form.  [O o; Z Z] [Public]
  768. X(defun math-normalize (a)
  769. X  (cond
  770. X   ((not (consp a))
  771. X    (if (integerp a)
  772. X    (if (or (>= a 1000000) (<= a -1000000))
  773. X        (math-bignum a)
  774. X      a)
  775. X      a))
  776. X   ((eq (car a) 'bigpos)
  777. X    (if (eq (nth (1- (length a)) a) 0)
  778. X    (let* ((last (setq a (copy-sequence a))) (digs a))
  779. X      (while (setq digs (cdr digs))
  780. X        (or (eq (car digs) 0) (setq last digs)))
  781. X      (setcdr last nil)))
  782. X    (if (cdr (cdr (cdr a)))
  783. X    a
  784. X      (cond
  785. X       ((cdr (cdr a)) (+ (nth 1 a) (* (nth 2 a) 1000)))
  786. X       ((cdr a) (nth 1 a))
  787. X       (t 0))))
  788. X   ((eq (car a) 'bigneg)
  789. X    (if (eq (nth (1- (length a)) a) 0)
  790. X    (let* ((last (setq a (copy-sequence a))) (digs a))
  791. X      (while (setq digs (cdr digs))
  792. X        (or (eq (car digs) 0) (setq last digs)))
  793. X      (setcdr last nil)))
  794. X    (if (cdr (cdr (cdr a)))
  795. X    a
  796. X      (cond
  797. X       ((cdr (cdr a)) (- (+ (nth 1 a) (* (nth 2 a) 1000))))
  798. X       ((cdr a) (- (nth 1 a)))
  799. X       (t 0))))
  800. X   ((eq (car a) 'frac)
  801. X    (math-make-frac (math-normalize (nth 1 a))
  802. X            (math-normalize (nth 2 a))))
  803. X   ((eq (car a) 'float)
  804. X    (math-make-float (math-normalize (nth 1 a)) (nth 2 a)))
  805. X   ((eq (car a) 'cplx)
  806. X    (let ((real (math-normalize (nth 1 a)))
  807. X      (imag (math-normalize (nth 2 a))))
  808. X      (if (math-zerop imag) real (list 'cplx real imag))))
  809. X   ((eq (car a) 'polar)
  810. X    (calc-extensions)
  811. X    (math-normalize-polar a))
  812. X   ((eq (car a) 'hms)
  813. X    (calc-extensions)
  814. X    (math-normalize-hms a))
  815. X   ((eq (car a) 'mod)
  816. X    (calc-extensions)
  817. X    (math-normalize-mod a))
  818. X   ((eq (car a) 'sdev)
  819. X    (calc-extensions)
  820. X    (math-make-sdev (math-normalize (nth 1 a))
  821. X            (math-normalize (nth 2 a))))
  822. X   ((eq (car a) 'intv)
  823. X    (calc-extensions)
  824. X    (math-make-intv (nth 1 a)
  825. X            (math-normalize (nth 2 a))
  826. X            (math-normalize (nth 3 a))))
  827. X   ((eq (car a) 'vec)
  828. X    (cons 'vec (mapcar 'math-normalize (cdr a))))
  829. X   ((memq (car a) '(quote special-const))
  830. X    (math-normalize (nth 1 a)))
  831. X   ((eq (car a) 'var)
  832. X    a)
  833. X   ((or (integerp (car a)) (and (consp (car a))
  834. X                (not (eq (car (car a)) 'lambda))))
  835. X    (if (null (cdr a))
  836. X    (math-normalize (car a))
  837. X      (error "Can't use multi-valued function in an expression")))
  838. X   ((eq (car a) 'calcFunc-if)
  839. X    (calc-extensions)
  840. X    (math-normalize-logical-op a))
  841. X   (t
  842. X    (let ((args (mapcar 'math-normalize (cdr a))))
  843. X      (or (and calc-simplify-mode
  844. X           (symbolp (car a))
  845. X           (or (eq calc-simplify-mode 'none)
  846. X           (and (eq calc-simplify-mode 'num)
  847. X            (let ((aptr args))
  848. X              (while (and aptr (or (math-scalarp (car aptr))
  849. X                           (eq (car-safe (car aptr))
  850. X                           'mod)))
  851. X                (setq aptr (cdr aptr)))
  852. X              aptr)))
  853. X           (cons (car a) args))
  854. X      (condition-case err
  855. X          (let ((func (assq (car a) '( ( + . math-add )
  856. X                       ( - . math-sub )
  857. X                       ( * . math-mul )
  858. X                       ( / . math-div )
  859. X                       ( % . math-mod )
  860. X                       ( ^ . math-pow )
  861. X                       ( neg . math-neg )
  862. X                       ( | . math-concat ) ))))
  863. X        (if func
  864. X            (apply (cdr func) args)
  865. X          (and (or (consp (car a))
  866. X               (fboundp (car a))
  867. X               (and (not calc-extensions-loaded)
  868. X                (calc-extensions)
  869. X                (fboundp (car a))))
  870. X               (apply (car a) args))))
  871. X        (wrong-number-of-arguments
  872. X         (calc-record-why "Wrong number of arguments") nil)
  873. X        (wrong-type-argument
  874. X         (or calc-next-why (calc-record-why "Wrong type of argument"))
  875. X         nil)
  876. X        (args-out-of-range
  877. X         (calc-record-why "Argument out of range") nil)
  878. X        (inexact-result
  879. X         (calc-record-why "No exact representation for result") nil))
  880. X      (if (consp (car a))
  881. X          (math-dimension-error)
  882. X        (cons (car a) args))))))
  883. X)
  884. X
  885. X(defmacro math-with-extra-prec (delta &rest body)
  886. X  (` (math-normalize
  887. X      (let ((calc-internal-prec (+ calc-internal-prec (, delta))))
  888. X    (,@ body))))
  889. X)
  890. X(put 'math-with-extra-prec 'lisp-indent-hook 1)
  891. X
  892. X;;; Define "inexact-result" as an e-lisp error symbol.
  893. X(put 'inexact-result 'error-conditions '(error inexact-result calc-error))
  894. X(put 'inexact-result 'error-message "Calc internal error (inexact-result)")
  895. X
  896. X;;; Normalize a bignum digit list by trimming high-end zeros.  [L l]
  897. X(defun math-norm-bignum (a)
  898. X  (let ((digs a) (last nil))
  899. X    (while digs
  900. X      (or (eq (car digs) 0) (setq last digs))
  901. X      (setq digs (cdr digs)))
  902. X    (and last
  903. X     (progn
  904. X       (setcdr last nil)
  905. X       a)))
  906. X)
  907. X
  908. X
  909. X;;; Concatenate two vectors, or a vector and an object.  [V O O] [Public]
  910. X(defun math-concat (v1 v2)
  911. X  (if (stringp v1)
  912. X      (concat v1 v2)
  913. X    (calc-extensions)
  914. X    (if (and (math-objvecp v1) (math-objvecp v2))
  915. X    (append (if (and (math-vectorp v1)
  916. X             (or (math-matrixp v1)
  917. X                 (not (math-matrixp v2))))
  918. X            v1
  919. X          (list 'vec v1))
  920. X        (if (and (math-vectorp v2)
  921. X             (or (math-matrixp v2)
  922. X                 (not (math-matrixp v1))))
  923. X            (cdr v2)
  924. X          (list v2)))
  925. X      (list '| v1 v2)))
  926. X)
  927. X(defun calcFunc-vconcat (a b)
  928. X  (math-normalize (list '| a b))
  929. X)
  930. X
  931. X
  932. X;;; True if A is zero.  Works for un-normalized values.  [P n] [Public]
  933. X(defun math-zerop (a)
  934. X  (if (consp a)
  935. X      (cond ((memq (car a) '(bigpos bigneg))
  936. X         (while (eq (car (setq a (cdr a))) 0))
  937. X         (null a))
  938. X        ((memq (car a) '(frac float polar mod))
  939. X         (math-zerop (nth 1 a)))
  940. X        ((eq (car a) 'cplx)
  941. X         (and (math-zerop (nth 1 a)) (math-zerop (nth 2 a))))
  942. X        ((eq (car a) 'hms)
  943. X         (and (math-zerop (nth 1 a))
  944. X          (math-zerop (nth 2 a))
  945. X          (math-zerop (nth 3 a)))))
  946. X    (eq a 0))
  947. X)
  948. X;;; Faster in-line version zerop, normalized values only.
  949. X(defmacro Math-zerop (a)   ; [P N]
  950. X  (` (if (consp (, a))
  951. X     (and (not (memq (car (, a)) '(bigpos bigneg)))
  952. X          (if (eq (car (, a)) 'float)
  953. X          (eq (nth 1 (, a)) 0)
  954. X        (math-zerop (, a))))
  955. X       (eq (, a) 0)))
  956. X)
  957. X
  958. X(defun math-zerop-bignum (a)
  959. X  (and (eq (car a) 0)
  960. X       (progn
  961. X     (while (eq (car (setq a (cdr a))) 0))
  962. X     (null a)))
  963. X)
  964. X
  965. X(defmacro Math-natnum-lessp (a b)
  966. X  (` (if (consp (, a))
  967. X     (and (consp (, b))
  968. X          (= (math-compare-bignum (cdr (, a)) (cdr (, b))) -1))
  969. X       (or (consp (, b))
  970. X       (< (, a) (, b)))))
  971. X)
  972. X
  973. X(defmacro Math-integer-negp (a)
  974. X  (` (if (consp (, a))
  975. X     (eq (car (, a)) 'bigneg)
  976. X       (< (, a) 0)))
  977. X)
  978. X
  979. X(defmacro Math-integer-posp (a)
  980. X  (` (if (consp (, a))
  981. X     (eq (car (, a)) 'bigpos)
  982. X       (> (, a) 0)))
  983. X)
  984. X
  985. X;;; True if A is real and negative.  [P n] [Public]
  986. X(defun math-negp (a)
  987. X  (if (consp a)
  988. X      (cond ((eq (car a) 'bigpos) nil)
  989. X        ((eq (car a) 'bigneg) (cdr a))
  990. X        ((eq (car a) 'frac)
  991. X         (if (Math-integer-negp (nth 2 a))
  992. X         (Math-integer-posp (nth 1 a))
  993. X           (Math-integer-negp (nth 1 a))))
  994. X        ((eq (car a) 'float)
  995. X         (Math-integer-negp (nth 1 a)))
  996. X        ((eq (car a) 'hms)
  997. X         (if (math-zerop (nth 1 a))
  998. X         (if (math-zerop (nth 2 a))
  999. X             (math-negp (nth 3 a))
  1000. X           (math-negp (nth 2 a)))
  1001. X           (math-negp (nth 1 a))))
  1002. X        ((eq (car a) 'intv)
  1003. X         (or (math-negp (nth 3 a))
  1004. X         (and (math-zerop (nth 3 a))
  1005. X              (memq (nth 1 a) '(0 2))))))
  1006. X    (< a 0))
  1007. X)
  1008. X(defmacro Math-negp (a)
  1009. X  (` (if (consp (, a))
  1010. X     (or (eq (car (, a)) 'bigneg)
  1011. X         (and (not (eq (car (, a)) 'bigpos))
  1012. X          (if (memq (car (, a)) '(frac float))
  1013. X              (Math-integer-negp (nth 1 (, a)))
  1014. X            (math-negp (, a)))))
  1015. X       (< (, a) 0)))
  1016. X)
  1017. X
  1018. X;;; True if A is a negative number or an expression the starts with '-'.
  1019. X(defun math-looks-negp (a)   ; [P x] [Public]
  1020. X  (or (Math-negp a)
  1021. X      (eq (car-safe a) 'neg)
  1022. X      (and (memq (car-safe a) '(* /))
  1023. X       (or (math-looks-negp (nth 1 a))
  1024. X           (math-looks-negp (nth 2 a)))))
  1025. X)
  1026. X(defmacro Math-looks-negp (a)   ; [P x] [Public]
  1027. X  (` (or (Math-negp (, a))
  1028. X     (and (consp (, a)) (or (eq (car (, a)) 'neg)
  1029. X                (and (memq (car (, a)) '(* /))
  1030. X                     (or (math-looks-negp (nth 1 (, a)))
  1031. X                     (math-looks-negp (nth 2 (, a)))))))))
  1032. X)
  1033. X
  1034. X;;; True if A is real and positive.  [P n] [Public]
  1035. X(defun math-posp (a)
  1036. X  (if (consp a)
  1037. X      (cond ((eq (car a) 'bigpos) (cdr a))
  1038. X        ((eq (car a) 'bigneg) nil)
  1039. X        ((eq (car a) 'frac)
  1040. X         (if (Math-integer-negp (nth 2 a))
  1041. X         (Math-integer-negp (nth 1 a))
  1042. X           (Math-integer-posp (nth 1 a))))
  1043. X        ((eq (car a) 'float)
  1044. X         (Math-integer-posp (nth 1 a)))
  1045. X        ((eq (car a) 'hms)
  1046. X         (if (math-zerop (nth 1 a))
  1047. X         (if (math-zerop (nth 2 a))
  1048. X             (math-posp (nth 3 a))
  1049. X           (math-posp (nth 2 a)))
  1050. X           (math-posp (nth 1 a))))
  1051. X        ((eq (car a) 'mod)
  1052. X         (not (math-zerop (nth 1 a))))
  1053. X        ((eq (car a) 'intv)
  1054. X         (or (math-posp (nth 2 a))
  1055. X         (and (math-zerop (nth 2 a))
  1056. X              (memq (nth 1 a) '(0 1))))))
  1057. X    (> a 0))
  1058. X)
  1059. X(defmacro Math-posp (a)
  1060. X  (` (if (consp (, a))
  1061. X     (or (eq (car (, a)) 'bigpos)
  1062. X         (and (not (eq (car (, a)) 'bigneg))
  1063. X          (if (memq (car (, a)) '(frac float))
  1064. X              (Math-integer-posp (nth 1 (, a)))
  1065. X            (math-posp (, a)))))
  1066. X       (> (, a) 0)))
  1067. X)
  1068. X
  1069. X;;; True if A is a small or big integer.  [P x] [Public]
  1070. X(defun math-integerp (a)
  1071. X  (or (integerp a)
  1072. X      (memq (car-safe a) '(bigpos bigneg)))
  1073. X)
  1074. X(defmacro Math-integerp (a)
  1075. X  (` (or (not (consp (, a)))
  1076. X     (memq (car (, a)) '(bigpos bigneg))))
  1077. X)
  1078. X
  1079. X(fset 'math-fixnump (symbol-function 'integerp))
  1080. X(fset 'math-fixnatnump (symbol-function 'natnump))
  1081. X
  1082. X;;; True if A is (numerically) a non-negative integer.  [P N] [Public]
  1083. X(defun math-natnump (a)
  1084. X  (or (natnump a)
  1085. X      (eq (car-safe a) 'bigpos))
  1086. X)
  1087. X(defmacro Math-natnump (a)
  1088. X  (` (if (consp (, a))
  1089. X     (eq (car (, a)) 'bigpos)
  1090. X       (>= (, a) 0)))
  1091. X)
  1092. X
  1093. X;;; True if A is a rational (or integer).  [P x] [Public]
  1094. X(defun math-ratp (a)
  1095. X  (or (integerp a)
  1096. X      (memq (car-safe a) '(bigpos bigneg frac)))
  1097. X)
  1098. X(defmacro Math-ratp (a)
  1099. X  (` (or (not (consp (, a)))
  1100. X     (memq (car (, a)) '(bigpos bigneg frac))))
  1101. X)
  1102. X
  1103. X;;; True if A is a real (or rational).  [P x] [Public]
  1104. X(defun math-realp (a)
  1105. X  (or (integerp a)
  1106. X      (memq (car-safe a) '(bigpos bigneg frac float)))
  1107. X)
  1108. X(defmacro Math-realp (a)
  1109. X  (` (or (not (consp (, a)))
  1110. X     (memq (car (, a)) '(bigpos bigneg frac float))))
  1111. X)
  1112. X
  1113. X;;; True if A is a real or HMS form.  [P x] [Public]
  1114. X(defun math-anglep (a)
  1115. X  (or (integerp a)
  1116. X      (memq (car-safe a) '(bigpos bigneg frac float hms)))
  1117. X)
  1118. X(defmacro Math-anglep (a)
  1119. X  (` (or (not (consp (, a)))
  1120. X     (memq (car (, a)) '(bigpos bigneg frac float hms))))
  1121. X)
  1122. X
  1123. X;;; True if A is a floating-point real or complex number.  [P x] [Public]
  1124. X(defun math-floatp (a)
  1125. X  (or (eq (car-safe a) 'float)
  1126. X      (and (memq (car-safe a) '(cplx polar mod sdev intv))
  1127. X       (or (math-floatp (nth 1 a))
  1128. X           (math-floatp (nth 2 a))
  1129. X           (and (eq (car a) 'intv) (math-floatp (nth 3 a))))))
  1130. X)
  1131. X
  1132. X;;; True if A is a number of any kind.  [P x] [Public]
  1133. X(defun math-numberp (a)
  1134. X  (or (integerp a)
  1135. X      (memq (car-safe a) '(bigpos bigneg frac float cplx polar)))
  1136. X)
  1137. X(defmacro Math-numberp (a)
  1138. X  (` (or (not (consp (, a)))
  1139. X     (memq (car (, a)) '(bigpos bigneg frac float cplx polar))))
  1140. X)
  1141. X
  1142. X;;; True if A is a complex number or angle.  [P x] [Public]
  1143. X(defun math-scalarp (a)
  1144. X  (or (integerp a)
  1145. X      (memq (car-safe a) '(bigpos bigneg frac float cplx polar hms)))
  1146. X)
  1147. X(defmacro Math-scalarp (a)
  1148. X  (` (or (not (consp (, a)))
  1149. X     (memq (car (, a)) '(bigpos bigneg frac float cplx polar hms))))
  1150. X)
  1151. X
  1152. X;;; True if A is a vector.  [P x] [Public]
  1153. X(defun math-vectorp (a)
  1154. X  (eq (car-safe a) 'vec)
  1155. X)
  1156. X(defmacro Math-vectorp (a)
  1157. X  (` (and (consp (, a)) (eq (car (, a)) 'vec)))
  1158. X)
  1159. X
  1160. X;;; True if A is a number or a vector.  [P x] [Public]
  1161. X(defun math-numvecp (a)
  1162. X  (or (Math-numberp a)
  1163. X      (Math-vectorp a))
  1164. X)
  1165. X
  1166. X;;; True if A is numerically (but not literally) an integer.  [P x] [Public]
  1167. X(defun math-messy-integerp (a)
  1168. X  (cond
  1169. X   ((eq (car-safe a) 'float) (>= (nth 2 a) 0))
  1170. X   ((eq (car-safe a) 'frac) (Math-integerp (math-normalize a))))
  1171. X)
  1172. X(defmacro Math-messy-integerp (a)
  1173. X  (` (and (consp (, a))
  1174. X      (eq (car (, a)) 'float)
  1175. X      (>= (nth 2 (, a)) 0)))
  1176. X)
  1177. X
  1178. X;;; True if A is any scalar data object.  [P x]
  1179. X(defun math-objectp (a)    ;  [Public]
  1180. X  (or (integerp a)
  1181. X      (memq (car-safe a) '(bigpos bigneg frac float cplx
  1182. X                  polar hms sdev intv mod)))
  1183. X)
  1184. X(defmacro Math-objectp (a)    ;  [Public]
  1185. X  (` (or (not (consp (, a)))
  1186. X     (memq (car (, a))
  1187. X           '(bigpos bigneg frac float cplx polar hms sdev intv mod))))
  1188. X)
  1189. X
  1190. X;;; True if A is any vector or scalar data object.  [P x]
  1191. X(defun math-objvecp (a)    ;  [Public]
  1192. X  (or (integerp a)
  1193. X      (memq (car-safe a) '(bigpos bigneg frac float cplx polar
  1194. X                  hms sdev intv mod vec incomplete)))
  1195. X)
  1196. X(defmacro Math-objvecp (a)    ;  [Public]
  1197. X  (` (or (not (consp (, a)))
  1198. X     (memq (car (, a))
  1199. X           '(bigpos bigneg frac float cplx polar hms sdev intv mod vec))))
  1200. X)
  1201. X
  1202. X
  1203. X;;; True if A is an even integer.  [P R R] [Public]
  1204. X(defun math-evenp (a)
  1205. X  (if (consp a)
  1206. X      (and (memq (car a) '(bigpos bigneg))
  1207. X       (= (% (nth 1 a) 2) 0))
  1208. X    (= (% a 2) 0))
  1209. X)
  1210. X
  1211. X;;; Compute A / 2, for small or big integer A.  [I i]
  1212. X;;; If A is negative, type of truncation is undefined.
  1213. X(defun math-div2 (a)
  1214. X  (if (consp a)
  1215. X      (if (cdr a)
  1216. X      (math-normalize (cons (car a) (math-div2-bignum (cdr a))))
  1217. X    0)
  1218. X    (/ a 2))
  1219. X)
  1220. X
  1221. X(defun math-div2-bignum (a)   ; [l l]
  1222. X  (cond
  1223. X   ((null (cdr a)) (list (/ (car a) 2)))
  1224. X   (t (cons (+ (/ (car a) 2) (* (% (nth 1 a) 2) 500))
  1225. X        (math-div2-bignum (cdr a)))))
  1226. X)
  1227. X
  1228. X
  1229. X;;; Verify that A is a complete object and return A.  [x x] [Public]
  1230. X(defun math-check-complete (a)
  1231. X  (cond ((integerp a) a)
  1232. X    ((eq (car-safe a) 'incomplete)
  1233. X     (cond ((memq (nth 1 a) '(cplx polar))
  1234. X        (error "Complex number is incomplete"))
  1235. X           ((eq (nth 1 a) 'vec)
  1236. X        (error "Vector is incomplete"))
  1237. X           ((eq (nth 1 a) 'intv)
  1238. X        (error "Interval form is incomplete"))
  1239. X           (t (error "Object is incomplete"))))
  1240. X    ((consp a) a)
  1241. X    (t (error "Invalid data object encountered")))
  1242. X)
  1243. X
  1244. X;;; Reject an argument to a calculator function.  [Public]
  1245. X(defun math-reject-arg (&optional a p)
  1246. X  (calc-record-why p a)
  1247. X  (signal 'wrong-type-argument (and a (if p (list p a) (list a))))
  1248. X)
  1249. X
  1250. X
  1251. X;;; Coerce A to be an integer (by truncation toward zero).  [I N] [Public]
  1252. X(defun math-trunc (a)
  1253. X  (cond ((Math-integerp a) a)
  1254. X    ((Math-looks-negp a)
  1255. X     (math-neg (math-trunc (math-neg a))))
  1256. X    ((eq (car a) 'float) (math-scale-int (nth 1 a) (nth 2 a)))
  1257. X    ((eq (car a) 'frac) (math-quotient (nth 1 a) (nth 2 a)))
  1258. X    (t (calc-extensions)
  1259. X       (math-trunc-fancy a)))
  1260. X)
  1261. X(fset 'calcFunc-trunc (symbol-function 'math-trunc))
  1262. X
  1263. X;;; Coerce A to be an integer (by truncation toward minus infinity).  [I N]
  1264. X(defun math-floor (a)    ;  [Public]
  1265. X  (cond ((Math-integerp a) a)
  1266. X    ((Math-messy-integerp a) (math-trunc a))
  1267. X    ((Math-realp a)
  1268. X     (if (Math-negp a)
  1269. X         (math-add (math-trunc a) -1)
  1270. X       (math-trunc a)))
  1271. X    (t (calc-extensions)
  1272. X       (math-floor-fancy a)))
  1273. X)
  1274. X(fset 'calcFunc-floor (symbol-function 'math-floor))
  1275. X
  1276. X
  1277. X;;; Coerce integer A to be a bignum.  [B S]
  1278. X(defun math-bignum (a)
  1279. X  (if (>= a 0)
  1280. X      (cons 'bigpos (math-bignum-big a))
  1281. X    (cons 'bigneg (math-bignum-big (- a))))
  1282. X)
  1283. X
  1284. X(defun math-bignum-big (a)   ; [L s]
  1285. X  (if (= a 0)
  1286. X      nil
  1287. X    (cons (% a 1000) (math-bignum-big (/ a 1000))))
  1288. X)
  1289. X
  1290. X
  1291. X;;; Build a normalized fraction.  [R I I]
  1292. X;;; (This could probably be implemented more efficiently than using the
  1293. X;;;  the plain gcd algorithm.)
  1294. X(defun math-make-frac (num den)
  1295. X  (if (Math-integer-negp den)
  1296. X      (setq num (math-neg num)
  1297. X        den (math-neg den)))
  1298. X  (let ((gcd (math-gcd num den)))
  1299. X    (if (eq gcd 1)
  1300. X    (if (eq den 1)
  1301. X        num
  1302. X      (list 'frac num den))
  1303. X      (if (equal gcd den)
  1304. X      (math-quotient num gcd)
  1305. X    (list 'frac (math-quotient num gcd) (math-quotient den gcd)))))
  1306. X)
  1307. X
  1308. X;;; Build a normalized floating-point number.  [F I S]
  1309. X(defun math-make-float (mant exp)
  1310. X  (if (eq mant 0)
  1311. X      '(float 0 0)
  1312. X    (let* ((ldiff (- calc-internal-prec (math-numdigs mant))))
  1313. X      (if (< ldiff 0)
  1314. X      (setq mant (math-scale-rounding mant ldiff)
  1315. X        exp (- exp ldiff))))
  1316. X    (if (consp mant)
  1317. X    (let ((digs (cdr mant)))
  1318. X      (if (= (% (car digs) 10) 0)
  1319. X          (progn
  1320. X        (while (= (car digs) 0)
  1321. X          (setq digs (cdr digs)
  1322. X            exp (+ exp 3)))
  1323. X        (while (= (% (car digs) 10) 0)
  1324. X          (setq digs (math-div10-bignum digs)
  1325. X            exp (1+ exp)))
  1326. X        (setq mant (math-normalize (cons (car mant) digs))))))
  1327. X      (while (= (% mant 10) 0)
  1328. X    (setq mant (/ mant 10)
  1329. X          exp (1+ exp))))
  1330. X    (list 'float mant exp))
  1331. X)
  1332. X
  1333. X(defun math-div10-bignum (a)   ; [l l]
  1334. X  (cond
  1335. X   ((null (cdr a)) (list (/ (car a) 10)))
  1336. X   (t (cons (+ (/ (car a) 10) (* (% (nth 1 a) 10) 100))
  1337. X        (math-div10-bignum (cdr a)))))
  1338. X)
  1339. X
  1340. X;;; Coerce A to be a float.  [F N; V V] [Public]
  1341. X(defun math-float (a)
  1342. X  (cond ((Math-integerp a) (math-make-float a 0))
  1343. X    ((eq (car a) 'frac) (math-div (math-float (nth 1 a)) (nth 2 a)))
  1344. X    ((eq (car a) 'float) a)
  1345. X    ((memq (car a) '(cplx polar vec hms sdev intv mod))
  1346. X     (cons (car a) (mapcar 'math-float (cdr a))))
  1347. X    (t (math-reject-arg a 'objectp)))
  1348. X)
  1349. X(fset 'calcFunc-float (symbol-function 'math-float))
  1350. X
  1351. X
  1352. X;;; Compute the negative of A.  [O O; o o] [Public]
  1353. X(defmacro Math-integer-neg (a)
  1354. X  (` (if (consp (, a))
  1355. X     (if (eq (car (, a)) 'bigpos)
  1356. X         (cons 'bigneg (cdr (, a)))
  1357. X       (cons 'bigpos (cdr (, a))))
  1358. X       (- (, a))))
  1359. X)
  1360. X(defun math-neg (a)
  1361. X  (cond ((not (consp a)) (- a))
  1362. X    ((eq (car a) 'bigpos) (cons 'bigneg (cdr a)))
  1363. X    ((eq (car a) 'bigneg) (cons 'bigpos (cdr a)))
  1364. X    ((memq (car a) '(frac float))
  1365. X     (list (car a) (Math-integer-neg (nth 1 a)) (nth 2 a)))
  1366. X    ((memq (car a) '(cplx vec hms))
  1367. X     (cons (car a) (mapcar 'math-neg (cdr a))))
  1368. X    (t (math-neg-fancy a)))
  1369. X)
  1370. X(defun calcFunc-neg (a)
  1371. X  (math-normalize (list 'neg a))
  1372. X)
  1373. X
  1374. X
  1375. X;;; Compute the number of decimal digits in integer A.  [S I]
  1376. X(defun math-numdigs (a)
  1377. X  (if (consp a)
  1378. X      (if (cdr a)
  1379. X      (let* ((len (1- (length a)))
  1380. X         (top (nth len a)))
  1381. X        (+ (* len 3) (cond ((>= top 100) 0) ((>= top 10) -1) (t -2))))
  1382. X    0)
  1383. X    (cond ((>= a 100) (+ (math-numdigs (/ a 1000)) 3))
  1384. X      ((>= a 10) 2)
  1385. X      ((>= a 1) 1)
  1386. X      ((= a 0) 0)
  1387. X      ((> a -10) 1)
  1388. X      ((> a -100) 2)
  1389. X      (t (math-numdigs (- a)))))
  1390. X)
  1391. X
  1392. X;;; Multiply (with truncation toward 0) the integer A by 10^N.  [I i S]
  1393. X(defun math-scale-int (a n)
  1394. X  (cond ((= n 0) a)
  1395. X    ((> n 0) (math-scale-left a n))
  1396. X    (t (math-normalize (math-scale-right a (- n)))))
  1397. X)
  1398. X
  1399. X(defun math-scale-left (a n)   ; [I I S]
  1400. X  (if (= n 0)
  1401. X      a
  1402. X    (if (consp a)
  1403. X    (cons (car a) (math-scale-left-bignum (cdr a) n))
  1404. X      (if (>= n 3)
  1405. X      (if (or (>= a 1000) (<= a -1000))
  1406. X          (math-scale-left (math-bignum a) n)
  1407. X        (math-scale-left (* a 1000) (- n 3)))
  1408. X    (if (= n 2)
  1409. X        (if (or (>= a 10000) (<= a -10000))
  1410. X        (math-scale-left (math-bignum a) 2)
  1411. X          (* a 100))
  1412. X      (if (or (>= a 100000) (<= a -100000))
  1413. X          (math-scale-left (math-bignum a) 1)
  1414. X        (* a 10))))))
  1415. X)
  1416. X
  1417. X(defun math-scale-left-bignum (a n)
  1418. X  (if (>= n 3)
  1419. X      (while (>= (setq a (cons 0 a)
  1420. X               n (- n 3)) 3)))
  1421. X  (if (> n 0)
  1422. X      (math-mul-bignum-digit a (if (= n 2) 100 10) 0)
  1423. X    a)
  1424. X)
  1425. X
  1426. X(defun math-scale-right (a n)   ; [i i S]
  1427. X  (if (= n 0)
  1428. X      a
  1429. X    (if (consp a)
  1430. X    (cons (car a) (math-scale-right-bignum (cdr a) n))
  1431. X      (if (<= a 0)
  1432. X      (if (= a 0)
  1433. X          0
  1434. X        (- (math-scale-right (- a) n)))
  1435. X    (if (>= n 3)
  1436. X        (while (and (> (setq a (/ a 1000)) 0)
  1437. X            (>= (setq n (- n 3)) 3))))
  1438. X    (if (= n 2)
  1439. X        (/ a 100)
  1440. X      (if (= n 1)
  1441. X          (/ a 10)
  1442. X        a)))))
  1443. X)
  1444. X
  1445. X(defun math-scale-right-bignum (a n)   ; [L L S; l l S]
  1446. X  (if (>= n 3)
  1447. X      (setq a (nthcdr (/ n 3) a)
  1448. X        n (% n 3)))
  1449. X  (if (> n 0)
  1450. X      (cdr (math-mul-bignum-digit a (if (= n 2) 10 100) 0))
  1451. X    a)
  1452. X)
  1453. X
  1454. X;;; Multiply (with rounding) the integer A by 10^N.   [I i S]
  1455. X(defun math-scale-rounding (a n)
  1456. X  (cond ((>= n 0)
  1457. X     (math-scale-left a n))
  1458. X    ((consp a)
  1459. X     (math-normalize
  1460. X      (cons (car a)
  1461. X        (let ((val (if (< n -3)
  1462. X                   (math-scale-right-bignum (cdr a) (- -3 n))
  1463. X                 (if (= n -2)
  1464. X                 (math-mul-bignum-digit (cdr a) 10 0)
  1465. X                   (if (= n -1)
  1466. X                   (math-mul-bignum-digit (cdr a) 100 0)
  1467. X                 (cdr a))))))  ; n = -3
  1468. X          (if (and val (>= (car val) 500))
  1469. X              (if (cdr val)
  1470. X              (if (eq (car (cdr val)) 999)
  1471. X                  (math-add-bignum (cdr val) '(1))
  1472. X                (cons (1+ (car (cdr val))) (cdr (cdr val))))
  1473. X            '(1))
  1474. X            (cdr val))))))
  1475. X    (t
  1476. X     (if (< a 0)
  1477. X         (- (math-scale-rounding (- a) n))
  1478. X       (if (= n -1)
  1479. X           (/ (+ a 5) 10)
  1480. X         (/ (+ (math-scale-right a (- -1 n)) 5) 10)))))
  1481. X)
  1482. X
  1483. X
  1484. X;;; Compute the sum of A and B.  [O O O] [Public]
  1485. X(defun math-add (a b)
  1486. X  (or
  1487. X   (and (not (or (consp a) (consp b)))
  1488. X    (progn
  1489. X      (setq a (+ a b))
  1490. X      (if (or (<= a -1000000) (>= a 1000000))
  1491. X          (math-bignum a)
  1492. X        a)))
  1493. X   (and (Math-zerop a) (not (eq (car-safe a) 'mod))
  1494. X    (if (and (math-floatp a) (Math-ratp b)) (math-float b) b))
  1495. X   (and (Math-zerop b) (not (eq (car-safe b) 'mod))
  1496. X    (if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
  1497. X   (and (Math-objvecp a) (Math-objvecp b)
  1498. X    (or
  1499. X     (and (Math-integerp a) (Math-integerp b)
  1500. X          (progn
  1501. X        (or (consp a) (setq a (math-bignum a)))
  1502. X        (or (consp b) (setq b (math-bignum b)))
  1503. X        (if (eq (car a) 'bigneg)
  1504. X            (if (eq (car b) 'bigneg)
  1505. X            (cons 'bigneg (math-add-bignum (cdr a) (cdr b)))
  1506. X              (math-normalize
  1507. X               (let ((diff (math-sub-bignum (cdr b) (cdr a))))
  1508. X             (if (eq diff 'neg)
  1509. X                 (cons 'bigneg (math-sub-bignum (cdr a) (cdr b)))
  1510. X               (cons 'bigpos diff)))))
  1511. X          (if (eq (car b) 'bigneg)
  1512. X              (math-normalize
  1513. X               (let ((diff (math-sub-bignum (cdr a) (cdr b))))
  1514. X             (if (eq diff 'neg)
  1515. X                 (cons 'bigneg (math-sub-bignum (cdr b) (cdr a)))
  1516. X               (cons 'bigpos diff))))
  1517. X            (cons 'bigpos (math-add-bignum (cdr a) (cdr b)))))))
  1518. X     (and (Math-ratp a) (Math-ratp b)
  1519. X          (if (eq (car-safe a) 'frac)
  1520. X          (if (eq (car-safe b) 'frac)
  1521. X              (math-make-frac (math-add (math-mul (nth 1 a) (nth 2 b))
  1522. X                        (math-mul (nth 2 a) (nth 1 b)))
  1523. X                      (math-mul (nth 2 a) (nth 2 b)))
  1524. X            (math-make-frac (math-add (nth 1 a)
  1525. X                          (math-mul (nth 2 a) b))
  1526. X                    (nth 2 a)))
  1527. X        (math-make-frac (math-add (math-mul a (nth 2 b))
  1528. X                      (nth 1 b))
  1529. X                (nth 2 b))))
  1530. X     (and (Math-realp a) (Math-realp b)
  1531. X          (progn
  1532. X        (or (and (consp a) (eq (car a) 'float))
  1533. X            (setq a (math-float a)))
  1534. X        (or (and (consp b) (eq (car b) 'float))
  1535. X            (setq b (math-float b)))
  1536. X        (math-add-float a b)))
  1537. X     (and (calc-extensions)
  1538. X          (math-add-objects-fancy a b))))
  1539. X   (and (calc-extensions)
  1540. X    (math-add-symb-fancy a b)))
  1541. X)
  1542. X(defun calcFunc-add (&rest rest)
  1543. X  (if rest
  1544. X      (let ((a (car rest)))
  1545. X    (while (setq rest (cdr rest))
  1546. X      (setq a (list '+ a (car rest))))
  1547. X    (math-normalize a))
  1548. X    0)
  1549. X)
  1550. X
  1551. X(defun math-add-bignum (a b)   ; [L L L; l l l]
  1552. X  (if a
  1553. X      (if b
  1554. X      (let* ((a (copy-sequence a)) (aa a) (carry nil) sum)
  1555. X        (while (and aa b)
  1556. X          (if carry
  1557. X          (if (< (setq sum (+ (car aa) (car b))) 999)
  1558. X              (progn
  1559. X            (setcar aa (1+ sum))
  1560. X            (setq carry nil))
  1561. X            (setcar aa (+ sum -999)))
  1562. X        (if (< (setq sum (+ (car aa) (car b))) 1000)
  1563. X            (setcar aa sum)
  1564. X          (setcar aa (+ sum -1000))
  1565. X          (setq carry t)))
  1566. X          (setq aa (cdr aa)
  1567. X            b (cdr b)))
  1568. X        (if carry
  1569. X        (if b
  1570. X            (nconc a (math-add-bignum b '(1)))
  1571. X          (while (eq (car aa) 999)
  1572. X            (setcar aa 0)
  1573. X            (setq aa (cdr aa)))
  1574. X          (if aa
  1575. X              (progn
  1576. X            (setcar aa (1+ (car aa)))
  1577. X            a)
  1578. X            (nconc a '(1))))
  1579. X          (if b
  1580. X          (nconc a b)
  1581. X        a)))
  1582. X    a)
  1583. X    b)
  1584. X)
  1585. X
  1586. X(defun math-sub-bignum (a b)   ; [l l l]
  1587. X  (if b
  1588. X      (if a
  1589. X      (let* ((a (copy-sequence a)) (aa a) (borrow nil) sum)
  1590. X        (while (and aa b)
  1591. X          (if borrow
  1592. X          (if (>= (setq diff (- (car aa) (car b))) 1)
  1593. X              (progn
  1594. X            (setcar aa (1- diff))
  1595. X            (setq borrow nil))
  1596. X            (setcar aa (+ diff 999)))
  1597. X        (if (>= (setq diff (- (car aa) (car b))) 0)
  1598. X            (setcar aa diff)
  1599. X          (setcar aa (+ diff 1000))
  1600. X          (setq borrow t)))
  1601. X          (setq aa (cdr aa)
  1602. X            b (cdr b)))
  1603. X        (if borrow
  1604. X        (progn
  1605. X          (while (eq (car aa) 0)
  1606. X            (setcar aa 999)
  1607. X            (setq aa (cdr aa)))
  1608. X          (if aa
  1609. X              (progn
  1610. X            (setcar aa (1- (car aa)))
  1611. X            a)
  1612. X            'neg))
  1613. X          (while (eq (car b) 0)
  1614. X        (setq b (cdr b)))
  1615. X          (if b
  1616. X          'neg
  1617. X        a)))
  1618. X    (while (eq (car b) 0)
  1619. X      (setq b (cdr b)))
  1620. X    (and b
  1621. X         'neg))
  1622. X    a)
  1623. X)
  1624. X
  1625. X(defun math-add-float (a b)   ; [F F F]
  1626. X  (let ((ediff (- (nth 2 a) (nth 2 b))))
  1627. X    (if (>= ediff 0)
  1628. X    (if (>= ediff (+ calc-internal-prec calc-internal-prec))
  1629. X        a
  1630. X      (math-make-float (math-add (nth 1 b)
  1631. X                     (math-scale-int (nth 1 a) ediff))
  1632. X               (nth 2 b)))
  1633. X      (if (>= (setq ediff (- ediff))
  1634. X          (+ calc-internal-prec calc-internal-prec))
  1635. X      b
  1636. X    (math-make-float (math-add (nth 1 a)
  1637. X                   (math-scale-int (nth 1 b) ediff))
  1638. X             (nth 2 a)))))
  1639. X)
  1640. X
  1641. X;;; Compute the difference of A and B.  [O O O] [Public]
  1642. X(defun math-sub (a b)
  1643. X  (if (or (consp a) (consp b))
  1644. X      (math-add a (math-neg b))
  1645. X    (setq a (- a b))
  1646. X    (if (or (<= a -1000000) (>= a 1000000))
  1647. X    (math-bignum a)
  1648. X      a))
  1649. X)
  1650. X(defun calcFunc-sub (&rest rest)
  1651. X  (if rest
  1652. X      (let ((a (car rest)))
  1653. X    (while (setq rest (cdr rest))
  1654. X      (setq a (list '- a (car rest))))
  1655. X    (math-normalize a))
  1656. X    0)
  1657. X)
  1658. X
  1659. X(defun math-sub-float (a b)   ; [F F F]
  1660. X  (let ((ediff (- (nth 2 a) (nth 2 b))))
  1661. X    (if (>= ediff 0)
  1662. X    (if (>= ediff (+ calc-internal-prec calc-internal-prec))
  1663. X        a
  1664. X      (math-make-float (math-add (Math-integer-neg (nth 1 b))
  1665. X                     (math-scale-int (nth 1 a) ediff))
  1666. X               (nth 2 b)))
  1667. X      (if (>= (setq ediff (- ediff))
  1668. X          (+ calc-internal-prec calc-internal-prec))
  1669. X      b
  1670. X    (math-make-float (math-add (nth 1 a)
  1671. X                   (Math-integer-neg
  1672. X                    (math-scale-int (nth 1 b) ediff)))
  1673. X             (nth 2 a)))))
  1674. X)
  1675. X
  1676. X
  1677. X;;; Compute the product of A and B.  [O O O] [Public]
  1678. X(defun math-mul (a b)
  1679. X  (or
  1680. X   (and (not (consp a)) (not (consp b))
  1681. X    (< a 1000) (> a -1000) (< b 1000) (> b -1000)
  1682. X    (* a b))
  1683. X   (and (Math-zerop a) (not (eq (car-safe b) 'mod))
  1684. X    (if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
  1685. X   (and (Math-zerop b) (not (eq (car-safe a) 'mod))
  1686. X    (if (and (math-floatp a) (Math-ratp b)) (math-float b) b))
  1687. X   (and (Math-objvecp a) (Math-objvecp b)
  1688. X    (or
  1689. X     (and (Math-integerp a) (Math-integerp b)
  1690. X          (progn
  1691. X        (or (consp a) (setq a (math-bignum a)))
  1692. X        (or (consp b) (setq b (math-bignum b)))
  1693. X        (math-normalize
  1694. X         (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
  1695. X               (if (cdr (cdr a))
  1696. X               (if (cdr (cdr b))
  1697. X                   (math-mul-bignum (cdr a) (cdr b))
  1698. X                 (math-mul-bignum-digit (cdr a) (nth 1 b) 0))
  1699. X             (math-mul-bignum-digit (cdr b) (nth 1 a) 0))))))
  1700. X     (and (Math-ratp a) (Math-ratp b)
  1701. X          (if (eq (car-safe a) 'frac)
  1702. X          (if (eq (car-safe b) 'frac)
  1703. X              (math-make-frac (math-mul (nth 1 a) (nth 1 b))
  1704. X                      (math-mul (nth 2 a) (nth 2 b)))
  1705. X            (math-make-frac (math-mul (nth 1 a) b)
  1706. X                    (nth 2 a)))
  1707. X        (math-make-frac (math-mul a (nth 1 b))
  1708. X                (nth 2 b))))
  1709. X     (and (Math-realp a) (Math-realp b)
  1710. X          (progn
  1711. X        (or (and (consp a) (eq (car a) 'float))
  1712. X            (setq a (math-float a)))
  1713. X        (or (and (consp b) (eq (car b) 'float))
  1714. X            (setq b (math-float b)))
  1715. X        (math-make-float (math-mul (nth 1 a) (nth 1 b))
  1716. X                 (+ (nth 2 a) (nth 2 b)))))
  1717. X     (and (calc-extensions)
  1718. X          (math-mul-objects-fancy a b))))
  1719. X   (and (calc-extensions)
  1720. X    (math-mul-symb-fancy a b)))
  1721. X)
  1722. X
  1723. X(defun calcFunc-mul (&rest rest)
  1724. X  (if rest
  1725. X      (let ((a (car rest)))
  1726. X    (while (setq rest (cdr rest))
  1727. X      (setq a (list '* a (car rest))))
  1728. X    (math-normalize a))
  1729. X    1)
  1730. X)
  1731. X
  1732. X;;; Multiply digit lists A and B.  [L L L; l l l]
  1733. X(defun math-mul-bignum (a b)
  1734. X  (and a b
  1735. X       (let* ((sum (if (<= (car b) 1)
  1736. X               (if (= (car b) 0)
  1737. X               (list 0)
  1738. X             (copy-sequence a))
  1739. X             (math-mul-bignum-digit a (car b) 0)))
  1740. X          (sump sum) c d aa prod)
  1741. X     (while (setq b (cdr b))
  1742. X       (setq ss (setq sump (or (cdr sump) (setcdr sump (list 0))))
  1743. X         d (car b)
  1744. X         c 0
  1745. X         aa a)
  1746. X       (while (progn
  1747. X            (setcar ss (% (setq prod (+ (+ (car ss) (* (car aa) d))
  1748. X                        c)) 1000))
  1749. X            (setq aa (cdr aa)))
  1750. X         (setq c (/ prod 1000)
  1751. X           ss (or (cdr ss) (setcdr ss (list 0)))))
  1752. X       (if (>= prod 1000)
  1753. X           (if (cdr ss)
  1754. X           (setcar (cdr ss) (+ (/ prod 1000) (car (cdr ss))))
  1755. X         (setcdr ss (list (/ prod 1000))))))
  1756. X     sum))
  1757. X)
  1758. X
  1759. X;;; Multiply digit list A by digit D.  [L L D D; l l D D]
  1760. X(defun math-mul-bignum-digit (a d c)
  1761. X  (and a
  1762. X       (if (<= d 1)
  1763. X       (and (= d 1) a)
  1764. X     (let* ((a (copy-sequence a)) (aa a) prod)
  1765. X       (while (progn
  1766. X            (setcar aa (% (setq prod (+ (* (car aa) d) c)) 1000))
  1767. X            (cdr aa))
  1768. X         (setq aa (cdr aa)
  1769. X           c (/ prod 1000)))
  1770. X       (if (>= prod 1000)
  1771. X           (setcdr aa (list (/ prod 1000))))
  1772. X       a)))
  1773. X)
  1774. X
  1775. X
  1776. X;;; Compute the square of A.  [O O] [Public]
  1777. X(defun math-sqr (a)
  1778. X  (if (eq (car-safe a) 'calcFunc-sqrt)
  1779. X      (nth 1 a)
  1780. X    (math-mul a a))
  1781. X)
  1782. X
  1783. X
  1784. X;;; Compute the integer (quotient . remainder) of A and B, which may be
  1785. X;;; small or big integers.  Type and consistency of truncation is undefined
  1786. X;;; if A or B is negative.  B must be nonzero.  [I.I I I] [Public]
  1787. X(defun math-idivmod (a b)
  1788. X  (if (eq b 0)
  1789. X      (math-reject-arg a "Division by zero"))
  1790. X  (if (or (consp a) (consp b))
  1791. X      (if (and (natnump b) (< b 1000))
  1792. X      (let ((res (math-div-bignum-digit (cdr a) b)))
  1793. X        (cons
  1794. X         (math-normalize (cons (car a) (car res)))
  1795. X         (cdr res)))
  1796. X    (or (consp a) (setq a (math-bignum a)))
  1797. X    (or (consp b) (setq b (math-bignum b)))
  1798. X    (let ((res (math-div-bignum (cdr a) (cdr b))))
  1799. X      (cons
  1800. X       (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
  1801. X                 (car res)))
  1802. X       (math-normalize (cons (car a) (cdr res))))))
  1803. X    (cons (/ a b) (% a b)))
  1804. X)
  1805. X
  1806. X(defun math-quotient (a b)   ; [I I I] [Public]
  1807. X  (if (and (not (consp a)) (not (consp b)))
  1808. X      (if (= b 0)
  1809. X      (math-reject-arg a "Division by zero")
  1810. X    (/ a b))
  1811. X    (if (and (natnump b) (< b 1000))
  1812. X    (if (= b 0)
  1813. X        (math-reject-arg a "Division by zero")
  1814. X      (math-normalize (cons (car a)
  1815. X                (car (math-div-bignum-digit (cdr a) b)))))
  1816. X      (or (consp a) (setq a (math-bignum a)))
  1817. X      (or (consp b) (setq b (math-bignum b)))
  1818. X      (let* ((alen (1- (length a)))
  1819. X         (blen (1- (length b)))
  1820. X         (d (/ 1000 (1+ (nth (1- blen) (cdr b)))))
  1821. X         (res (math-div-bignum-big (math-mul-bignum-digit (cdr a) d 0)
  1822. X                       (math-mul-bignum-digit (cdr b) d 0)
  1823. X                       alen blen)))
  1824. X    (math-normalize (cons (if (eq (car a) (car b)) 'bigpos 'bigneg)
  1825. X                  (car res))))))
  1826. X)
  1827. X
  1828. X(defun math-imod (a b)   ; [I I I] [Public]
  1829. X  (if (and (not (consp a)) (not (consp b)))
  1830. X      (if (= b 0)
  1831. X      (math-reject-arg a "Division by zero")
  1832. X    (% a b))
  1833. X    (cdr (math-idivmod a b)))
  1834. X)
  1835. X
  1836. X;;; Divide a bignum digit list by another.  [l.l l L]
  1837. X;;; The following division algorithm is borrowed from Knuth vol. II, sec. 4.3.1
  1838. X(defun math-div-bignum (a b)
  1839. X  (if (null (cdr b))
  1840. X      (let ((res (math-div-bignum-digit a (car b))))
  1841. X    (cons (car res) (list (cdr res))))
  1842. X    (let* ((alen (length a))
  1843. X       (blen (length b))
  1844. X       (d (/ 1000 (1+ (nth (1- blen) b))))
  1845. X       (res (math-div-bignum-big (math-mul-bignum-digit a d 0)
  1846. X                     (math-mul-bignum-digit b d 0)
  1847. X                     alen blen)))
  1848. X      (if (= d 1)
  1849. X      res
  1850. X    (cons (car res)
  1851. X          (car (math-div-bignum-digit (cdr res) d))))))
  1852. X)
  1853. X
  1854. X;;; Divide a bignum digit list by a digit.  [l.D l D]
  1855. X(defun math-div-bignum-digit (a b)
  1856. X  (if (null a)
  1857. X      '(nil . 0)
  1858. X    (let* ((res (math-div-bignum-digit (cdr a) b))
  1859. X       (num (+ (* (cdr res) 1000) (car a))))
  1860. X      (cons
  1861. X       (cons (/ num b) (car res))
  1862. X       (% num b))))
  1863. X)
  1864. X
  1865. X(defun math-div-bignum-big (a b alen blen)   ; [l.l l L]
  1866. X  (if (< alen blen)
  1867. X      (cons nil a)
  1868. X    (let* ((res (math-div-bignum-big (cdr a) b (1- alen) blen))
  1869. X       (num (cons (car a) (cdr res)))
  1870. X       (res2 (math-div-bignum-part num b blen)))
  1871. X      (cons
  1872. X       (cons (car res2) (car res))
  1873. X       (cdr res2))))
  1874. X)
  1875. X
  1876. X(defun math-div-bignum-part (a b blen)   ; a < b*1000  [D.l l L]
  1877. X  (let* ((num (+ (* (or (nth blen a) 0) 1000) (or (nth (1- blen) a) 0)))
  1878. X     (den (nth (1- blen) b))
  1879. X     (guess (min (/ num den) 999)))
  1880. X    (math-div-bignum-try a b (math-mul-bignum-digit b guess 0) guess))
  1881. X)
  1882. X
  1883. X(defun math-div-bignum-try (a b c guess)   ; [D.l l l D]
  1884. X  (let ((rem (math-sub-bignum a c)))
  1885. X    (if (eq rem 'neg)
  1886. X    (math-div-bignum-try a b (math-sub-bignum c b) (1- guess))
  1887. X      (cons guess rem)))
  1888. X)
  1889. X
  1890. X
  1891. X;;; Compute the quotient of A and B.  [O O N] [Public]
  1892. X(defun math-div (a b)
  1893. X  (or
  1894. X   (and (Math-zerop b)
  1895. X    (math-reject-arg a "Division by zero"))
  1896. X   (and (Math-zerop a) (not (eq (car-safe b) 'mod))
  1897. X    (if (and (math-floatp b) (Math-ratp a)) (math-float a) a))
  1898. X   (and (Math-objvecp a) (Math-objvecp b)
  1899. X    (or
  1900. X     (and (Math-integerp a) (Math-integerp b)
  1901. X          (if calc-prefer-frac
  1902. X          (math-make-frac a b)
  1903. X        (let ((q (math-idivmod a b)))
  1904. X          (if (eq (cdr q) 0)
  1905. X              (car q)
  1906. X            (math-div-float (math-make-float a 0)
  1907. X                    (math-make-float b 0))))))
  1908. X     (and (Math-ratp a) (Math-ratp b)
  1909. X          (if (eq (car-safe a) 'frac)
  1910. X          (if (eq (car-safe b) 'frac)
  1911. X              (math-make-frac (math-mul (nth 1 a) (nth 2 b))
  1912. X                      (math-mul (nth 2 a) (nth 1 b)))
  1913. X            (math-make-frac (nth 1 a)
  1914. X                    (math-mul (nth 2 a) b)))
  1915. X        (math-make-frac (math-mul a (nth 2 b))
  1916. X                (nth 1 b))))
  1917. X     (and (Math-realp a) (Math-realp b)
  1918. X          (progn
  1919. X        (or (and (consp a) (eq (car a) 'float))
  1920. X            (setq a (math-float a)))
  1921. X        (or (and (consp b) (eq (car b) 'float))
  1922. X            (setq b (math-float b)))
  1923. X        (math-div-float a b)))
  1924. X     (and (calc-extensions)
  1925. X          (math-div-objects-fancy a b))))
  1926. X   (and (calc-extensions)
  1927. X    (math-div-symb-fancy a b)))
  1928. X)
  1929. X(defun calcFunc-div (a &rest rest)
  1930. X  (while rest
  1931. X    (setq a (list '/ a (car rest))
  1932. X      rest (cdr rest)))
  1933. X  (math-normalize a)
  1934. X)
  1935. X
  1936. X(defun math-div-float (a b)   ; [F F F]
  1937. X  (let ((ldiff (max (- (1+ calc-internal-prec)
  1938. X               (- (math-numdigs (nth 1 a)) (math-numdigs (nth 1 b))))
  1939. SHAR_EOF
  1940. echo "End of part 2"
  1941. echo "File calc.el is continued in part 3"
  1942. echo "3" > s2_seq_.tmp
  1943. exit 0
  1944.